/*
#Copyright (c) 2013, Philippe Bordron <philippe.bordron@gmail.com>
#
# This file is part of SIPPER.
#
# DCC is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU LESSER GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# along with SIPPER.  If not, see <http://www.gnu.org/licenses/>
*/
package combi.wip.graph.algo.ksp.srdrPaths;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import combi.utils.Couple;
import combi.wip.graph.algo.ksp.LabelGroupeSommets;

import org.jgrapht.graph.DefaultDirectedWeightedGraph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.DirectedMaskSubgraph;

import combi.graph.Mask;

public class TraiteUnCheminSRDR extends Thread {

	protected ControleCheminsEnParalleleSRDR controle;
	protected Couple<Set<Integer>, Set<Integer>> query;
	protected String labelFin;
	protected String labelDeb;
	protected LabelGroupeSommets<Set<Integer>> labels;
	protected DefaultDirectedWeightedGraph<Integer, DefaultWeightedEdge> graph;
	protected Mask<Integer, DefaultWeightedEdge> maskBase;
	protected int fakeSrc;
	protected int fakeDest;
	protected int k;
	protected Map<Integer, Set<Integer>> twins;
	protected boolean useRank;
	protected String outFile;

	protected Mask<Integer, DefaultWeightedEdge> mask;
	protected DirectedMaskSubgraph<Integer, DefaultWeightedEdge> mod;
	protected double lengthPathLimit = Double.POSITIVE_INFINITY;

	public TraiteUnCheminSRDR(ControleCheminsEnParalleleSRDR controleCheminsEnParalleleSRDR,
			int nb_threads,
			DefaultDirectedWeightedGraph<Integer, DefaultWeightedEdge> graph,
			Mask<Integer, DefaultWeightedEdge> mask,
			int fakeSrc,
			int fakeDest,
			int k,
			Map<Integer, Set<Integer>> twins,
			Couple<Set<Integer>, Set<Integer>> query,
			boolean useRank,
			String labelDeb,
			String labelFin,
			String outFile)
	{
		//super(nb_threads);
		this.controle = controleCheminsEnParalleleSRDR;
		this.fakeSrc = fakeSrc;
		this.fakeDest = fakeDest;
		this.query = query;
		this.labelFin = labelFin;
		this.twins = twins;
		this.labelDeb = labelDeb;
		this.outFile = outFile;
		this.graph = graph;
		this.maskBase = mask;
		this.k = k;
		this.useRank = useRank;
	}


	public void run()
	{
		calcul();
		controle.remove();
	}

	public void calcul()
	{
		BufferedWriter out;
		mask = new Mask<Integer, DefaultWeightedEdge>(maskBase);
		mod = new DirectedMaskSubgraph<Integer, DefaultWeightedEdge>(graph, mask);

		for (Integer v : query.getFirst())
		{
			mask.removeEdge(graph.getEdge(fakeSrc,v)); // retrait des arcs masquants
		}
		for (Integer w : query.getSecond())
		{
			mask.removeEdge(graph.getEdge(w, fakeDest));
		}
		Ksp_Yen_SRDR<Integer, DefaultWeightedEdge> algo = new Ksp_Yen_SRDR<Integer, DefaultWeightedEdge>(mod, fakeSrc, fakeDest, k, twins, useRank);
		algo.setPathLimit(lengthPathLimit);
		algo.run();
//		Thread t = new Thread(algo);
//		t.start();
//		try {
//			t.join();
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		synchronized(this)
//		{
			try {
				out = new BufferedWriter(new FileWriter(outFile, true));

				out.write(labelDeb + "->" + labelFin + "\n");
				for(List<DefaultWeightedEdge> l : algo.getPaths())
				{
					//if (algo.getScoreChemin(l).getFirst() == 0)
					//{
					//	System.err.println("Zero weight path : "+ l);
					//}
					out.write(algo.getScoreChemin(l).getFirst() + "\t" + (l.size() - 1) +"\t"+algo.convertEdgesPath2NodesPath(cut(l))+"\n");
				}
				out.write("\n");
				out.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
//			for (Integer w : entry2)
//			{
//				mask.addEdge(graph.getEdge(w, fakeDest));
//			}

//		}
		mask.clear();
		/*for (Integer v : entry1)
		{
			mask.addEdge(graph.getEdge(fakeSrc,v));
		}*/
		//System.err.println("Thread finished");
	}


	private static List<DefaultWeightedEdge> cut (List<DefaultWeightedEdge> l)
	{
		l.remove(l.size()-1);
		l.remove(0);
		return l;
	}


	public void setPathLengthLimit(double lengthPathLimit) {
		this.lengthPathLimit  = lengthPathLimit;
	}

}
